package com.qf.shiro;

import com.qf.pojo.DtsAdmin;
import com.qf.service.AdminService;
import com.qf.service.DtsPermissionService;
import com.qf.service.RoleService;
import com.qf.util.bcrypt.BCryptPasswordEncoder;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Set;

/**
 * @author Wy
 * @version V1.0
 * @Project MavenDemo
 * @Package com.qf.shiro
 * @Description:
 * @Date 2022/6/15 16:40
 */
public class AdminAuthorizingRealm extends AuthorizingRealm {
    @Autowired
    private AdminService adminService;
    @Autowired
    private DtsPermissionService dtsPermissionService;
    @Autowired
    private RoleService service;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1. 获取认证后的当前用户对象, 这里将参数强转成我们自己封装的用户实体类对象
            DtsAdmin admin=(DtsAdmin)getAvailablePrincipal(principalCollection);
        //2. 根据用户对象获取角色ids
        Integer[] roleIds = admin.getRoleIds();
        //3. 根据角色id集合, 到数据库中查询对应的权限字符串集合
        Set<String> permSet = dtsPermissionService.queryByRoleIds(roleIds);
        //4. 根据角色id集合到数据库中查找对应的角色名称集合
        Set<String> roleSet = service.queryByIds(roleIds);
        //5. 将角色名称集合, 和权限字符串集合交给shiro框架
        SimpleAuthorizationInfo Info = new SimpleAuthorizationInfo();
        Info.setRoles(roleSet);
        Info.setStringPermissions(permSet);

        //6. 返回封装后的shiro权限对象

        return Info;
    }


    /**
     * 接收页面传入的用户名密码，根据数据库的用户密码进行校验
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //1获取用户页面输入的用户名密码
        //转换为对象形式
      UsernamePasswordToken user= (UsernamePasswordToken) token;
        String username = user.getUsername();
        String password = new String(user.getPassword());
        //2.判断用户名密码为不为空
        if(StringUtils.isEmpty(username)){
            throw  new AccountException("用户名为空");
        }
        //3.判断密码为不为空
        if(StringUtils.isEmpty(password)){
            throw  new AccountException("密码为空");
        }
        //4. 根据用户名, 获取用户对象集合
        List<DtsAdmin> adminByUserName = adminService.findAdminByUserName(username);
        //5. 判断如果获取不到用户对象, 返回异常提示信息
         if(adminByUserName==null||adminByUserName.size()==0){
             throw new AccountException("密码为空");
         }
         //6.如果用户对象大于一个，那么说明存在同名账户

        if(adminByUserName.size()>=2){
            throw  new UnknownAccountException("存在相同账户，请联系管理员");
        }
        DtsAdmin dtsAdmin = adminByUserName.get(0);
        //7. 判断如果密码不正确返回异常提示信息
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        //BCrypt工具类进行校验, 密码使用的BCrypt算法进行的加密
        //第一个参数是明文密码, 第二个参数是加密后的密码, 返回校验结果
        if(!encoder.matches(password, dtsAdmin.getPassword())){
            throw new UnknownAccountException("密码错误");
        }
        //8. 封装shiro指定的对象交给shiro框架处理
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(dtsAdmin,password,this.getName());
        return info;
    }
}
